package data.socket
{
	import data.events.SocketBaseEvent;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.ObjectEncoding;
	import flash.net.Socket;
	import flash.system.Security;
	import flash.utils.ByteArray;
	
	public class SocketBase extends EventDispatcher
	{
		private var _host:String;  
		private var _port:uint;
		private var isReadHead:Boolean=false;
		private var dataLen:int=0;
		private var _socket:Socket; 
		
		public function SocketBase()
		{
			_socket = new Socket();  

			_socket.addEventListener(Event.CONNECT, handler);
			_socket.addEventListener(Event.CLOSE, handler);
			_socket.addEventListener(IOErrorEvent.IO_ERROR, handler);
			_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, handler);
			_socket.addEventListener(ProgressEvent.SOCKET_DATA, handler);
		}
		
		/**
		 *事件状态 
		 */		
		private function handler(event:Event):void
		{  
			switch(event.type)
			{
				case Event.CLOSE:  
					dispatchEvent(new SocketBaseEvent(SocketBaseEvent.CLOSE));  
					break;  
				case Event.CONNECT:
					dispatchEvent(new SocketBaseEvent(SocketBaseEvent.CONNECT));
					break;
				case IOErrorEvent.IO_ERROR:
					dispatchEvent(new SocketBaseEvent(SocketBaseEvent.IO_ERROR));
					break;
				case SecurityErrorEvent.SECURITY_ERROR:  
					dispatchEvent(new SocketBaseEvent(SocketBaseEvent.SECURITY_ERROR));  
					break;
				case ProgressEvent.SOCKET_DATA:  
					SocketData();  
					break;  
			}  
		} 
		
		/**
		 *Socket连接主机地址
		 */		
		public function get host():String
		{  
			return _host;  
		}
		
		/**
		 *Socket连接端口 
		 */		
		public function get port():uint
		{  
			return _port;  
		}
		
		/**
		 *Socket连接状态
		 */		
		public function get connected():Boolean 
		{  
			return _socket.connected;  
		}  
		
		/**
		 *执行Socket连接 
		 * @param host 主机地址
		 * @param port 主机端口
		 */			
		public function connect(host:String, port:uint):void
		{
			_host = host;  
			_port = port;
			_socket.connect(_host, _port);  
		}  
		
		/**
		 *关闭Socket连接
		 */		
		public function close():void
		{  
			this._socket.close();  
		}  
		
		/**
		 * 发送Socket ByteArray数据包 
		 * @param socketPack Socket数据包
		 */
		public function sendByteArray(dataPack:ByteArray):void
		{		
			if(!connected || !dataPack)
			{
				return;  
			}
			
//			_socket.objectEncoding = ObjectEncoding.DEFAULT;
			
			var dataByte:ByteArray=new ByteArray();
			dataByte.writeUTF(dataPack.readUTF());
			dataByte.writeInt(dataPack.length);
			dataByte.writeBytes(dataPack, 0, dataPack.length);
			
			_socket.writeBytes(dataByte);
			_socket.flush();
			
			dispatchEvent(new SocketBaseEvent(SocketBaseEvent.SENDING, dataPack));
		}
		
		/**
		 * 发送Socket AMF3数据包 
		 * @param socketPack Socket数据包
		 */
		public function sendAMF(dataPack:Object):void
		{
			if(!connected || !dataPack)
			{
				return;  
			}
			
			_socket.objectEncoding = ObjectEncoding.AMF3;
			
			var bytes:ByteArray = new ByteArray();
			bytes.writeObject(dataPack);
			bytes.compress();
			
			var dataByte:ByteArray=new ByteArray();
			dataByte.writeInt(dataPack.dataTransferType);//数据包传输方式
			dataByte.writeInt(bytes.length);//数据包长度
			dataByte.writeBytes(bytes, 0, bytes.length);//数据包
			
			_socket.writeBytes(dataByte);
			_socket.flush();
			
			dispatchEvent(new SocketBaseEvent(SocketBaseEvent.SENDING, dataPack));
		}
		
		/**
		 *结果返回
		 */
		private function SocketData():void
		{
			if (!isReadHead && _socket.bytesAvailable > 8)
			{
				var headByte:ByteArray = new ByteArray();
				_socket.readBytes(headByte, 0, 8);
				var dataTransferType:int = headByte.readInt();//取得数据传输类型
				dataLen = headByte.readInt();//取得数据总长度
				isReadHead = true;
			}
			
			if (isReadHead && _socket.bytesAvailable >= dataLen)
			{
				try
				{
					var dataByte:ByteArray = new ByteArray();
					_socket.readBytes(dataByte, 0, dataLen); 
					isReadHead = false;
					//dataByte.uncompress();
					var dataObject:* = dataByte.readObject();
					dispatchEvent(new SocketBaseEvent(SocketBaseEvent.SOCKET_DATA, dataObject));
				}
				catch (error:Error)
				{
					dispatchEvent(new SocketBaseEvent(SocketBaseEvent.DECODE_ERROR));
				}
			}
			
			if(_socket.bytesAvailable > 0 && !isReadHead) SocketData();
		}
	}
}